iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 10
2
自我挑戰組

中年失業大叔的耍廢日記系列 第 10

第十天:收到明天是「特殊工作日」的通知

嗯?開機就收到明天是「特殊工作日」的通知,但是這兩天都要辛勤工作,沒差...出門寫作業去。

因為要用功,所以就到插座多的咖啡店。上班時間咖啡店人都不多,沒人跟我搶插座,很好...今天要完成一半的測試,同時覆蓋率要80%以上...開始,然後各種鬼打牆XD

原來的程式只是從範例修改的,寫得有點隨便阿,重點是有點難測試,考慮了一下幾個函數需要使用的參數,把他整理到consturctor函數裡面,不是全部都用到的,就改成各自的參數,然後原本直接呼叫的callback,也改成參數傳入,總算可以見人...Statement, Branch, Func, Line都超過80%,沒跑到的大致上都是catch,這樣應該可以。

結果這樣搞著就傍晚了XD,先來煮個麵吃~~

晚上還是看一下pptx viewer,畢竟昨天沒進度。之前處理的是副檔名為.rels的xml檔,今天來處理其他的xml檔。用原本的處理方式,轉出來的json會長這樣(docProps/core.xml):

{
  "type": "DOCUMENT_NODE",
  "value": "",
  "children": [
    {
      "type": "ELEMENT_NODE",
      "tagName": "cp:coreProperties",
      "attributes": {
        "xmlns:cp": "http://schemas.openxmlformats.org/package/2006/metadata/core-properties",
        "xmlns:dc": "http://purl.org/dc/elements/1.1/",
        "xmlns:dcterms": "http://purl.org/dc/terms/",
        "xmlns:dcmitype": "http://purl.org/dc/dcmitype/",
        "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance"
      },
      "value": "",
      "children": [
        {
          "type": "ELEMENT_NODE",
          "tagName": "dc:title",
          "attributes": {},
          "value": "Colour Pencils PowerPoint Template",
          "children": []
        },
        {
          "type": "ELEMENT_NODE",
          "tagName": "dc:creator",
          "attributes": {},
          "value": "Presentation Magazine",
          "children": []
        },
        {
          "type": "ELEMENT_NODE",
          "tagName": "cp:lastModifiedBy",
          "attributes": {},
          "value": "Hsu Ping Feng",
          "children": []
        },
        {
          "type": "ELEMENT_NODE",
          "tagName": "cp:revision",
          "attributes": {},
          "value": "58",
          "children": []
        },
        {
          "type": "ELEMENT_NODE",
          "tagName": "dcterms:created",
          "attributes": {
            "xsi:type": "dcterms:W3CDTF"
          },
          "value": "2009-11-03T13:35:13Z",
          "children": []
        },
        {
          "type": "ELEMENT_NODE",
          "tagName": "dcterms:modified",
          "attributes": {
            "xsi:type": "dcterms:W3CDTF"
          },
          "value": "2016-10-14T08:03:12Z",
          "children": []
        }
      ]
    }
  ]
}

其實就是用一個簡單的樹狀結構保留原本的xml結構跟資訊,這樣資訊雖然完整,但是看起來很不直覺。稍微調整一下讓他用屬性及child node的tag name當作物件的property,會比較容易理解。先改一下程式:

<!DOCTYPE html>
<html>

<head>
    <title>file reader</title>
    <style>
        .dropable {
            width: 99%;
            height: 100px;
            background-color: #369;
            color: white;
            border: solid 3px gray;
            border-radius: 5px;
            padding: 5px 5px 5px 5px;
        }

        .message {
            width: 99%;
            background-color: #ddd;
            border: solid 1px gray;
            border-radius: 5px;
            overflow: auto;
        }

        .preview {
            font-size: 10px;
        }
    </style>
</head>

<body>
    <div id="target" class="dropable">
        <select id="encoding">
            <option value="utf-8">utf-8</option>
            <option value="big5">big5</option>
            <option value="gb2312">gb2312</option>
            <option value="shift-jis">shift-jis</option>
        </select>
        <input type="file" id="file" />
        <div id="console"></div>
    </div>
    <div id="panel" class="message"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.11/pako_inflate.min.js"></script>
    <script src="lib/zipfs.js"></script>
    <script src="node_modules/xmlrun/index.js"></script>
    <script>
        var _target = document.getElementById('target');
        var _message = document.getElementById('panel');
        var _file = document.getElementById('file');
        _file.onchange = function(e) {
            clearlog();
            if (this.files.length > 0) {
                var reader = new FileReader();
                reader.onload = (e) => {
                    var buffer = e.target.result;
                    log('file size: ' + buffer.byteLength);
                    let encoding = document.getElementById('encoding').value;
                    let start = new Date().getTime();
                    zipfs(buffer, pako.inflateRaw, encoding, (err, files) => {
                        if (!!err) return console.log(err);
                        log(`in callback: ${files.length} files extracted.`);
                        log(`${(new Date().getTime()-start)} ms`);
                        let str = '<table border="1" cellspacing="0" cellpadding="5" width="99%"><tr><th>file name</th><th>buffer length</th><th>last modified date</th><th>last modified time</th><th>compressed size</th><th>uncompressed size</th></tr>';
                        files.forEach(file => {
                            str += `<tr><td>${file.file_name}</td><td>${file.content.length}</td><td>${zipfs.formatMSDOSDate(file.last_modified_date)}</td><td>${zipfs.formatMSDOSTime(file.last_modified_time)}</td><td>${file.compressed_size}</td><td>${file.uncompressed_size}</td></tr>`;
                            str += `<tr><td colspan="6" class="preview" style="overflow-x:hidden">`;
                            if (checkExt(file.file_name, '.rels')) {
                                let runner = xmlnode(zipfs.uintToString(file.content));
                                runner.setRunner('default', function(target) {
                                    if(!!target.child) {
                                        return target.child.reduce((acc, cur) => {
                                            Object.assign(acc, cur.run());
                                            return acc;
                                        }, {})
                                    }
                                    else return {};
                                });
                                runner.setRunner('Relationship', target => {
                                    let result = {};
                                    result[target.attr['Id']] = target.attr['Target'];
                                    result[target.attr['Target']] = target.attr['Id'];
                                    return result;
                                });
                                let obj = runner.run();
                                str += `<pre>${JSON.stringify(obj, null, 2)}</pre>`;
                            }

                            if (checkExt(file.file_name, '.xml')) {
                                let runner = xmlnode(zipfs.uintToString(file.content));
                                runner.setRunner('default', function(target) {
                                    /*let result = {
                                        type: xmlnode.utils.getNodeTypeDesc(target.type),
                                        tagName: target.tag,
                                        attributes: target.attr,
                                        value: target.val,
                                        children: []
                                    }
                                    if(!!target.child) {
                                        result.children = target.child.reduce((acc, cur) => {
                                            acc.push(cur.run());
                                            return acc;
                                        }, []);
                                    }
                                    return result;*/
                                    let result = {};
                                    if(!!target.attr) {
                                        result = Object.keys(target.attr).reduce((pre, cur) => {
                                            pre[cur] = target.attr[cur];
                                            return pre;
                                        }, {});
                                    }
                                    if(!!target.val) result._value = target.val;
                                    if(!!target.child && Array.isArray(target.child) && target.child.length > 0) {
                                        target.child.forEach(c => {
                                            if(!result[c.tag]) {
                                                result[c.tag] = c.run();
                                            } else {
                                                if(Array.isArray(result[c.tag])) {
                                                    result[c.tag].push(c.run());
                                                } else {
                                                    let _t = result[c.tag];
                                                    result[c.tag] = [];
                                                    result[c.tag].push(_t);
                                                    result[c.tag].push(c.run());
                                                }
                                            }
                                        });
                                    }
                                    return result;
                                });
                                let obj = runner.run();
                                str += `<pre>${JSON.stringify(obj, null, 2)}</pre>`;
                            }
                            if (checkExt(file.file_name, '.jpeg') || checkExt(file.file_name, '.jpg')) {
                                let im = new Image();
                                im.src = `data:image/jpeg;base64,${zipfs.arrayBufferToBase64(file.content)}`;
                                if(im.width > 1024) {
                                    str += `<img width="1024px" src="data:image/jpeg;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
                                } else {
                                    str += `<img src="data:image/jpeg;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
                                }
                            }
                            if (checkExt(file.file_name, '.png')) {
                                let im = new Image();
                                im.src = `data:image/png;base64,${zipfs.arrayBufferToBase64(file.content)}`;
                                if(im.width > 1024) {
                                    str += `<img width="1024px" src="data:image/png;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
                                } else {
                                    str += `<img src="data:image/png;base64,${zipfs.arrayBufferToBase64(file.content)}">`;
                                }
                            }
                            if (checkExt(file.file_name, '.mp3')) {
                                str += '<audio controls type="audio/mpeg" src="data:audio/mp3;base64,' +
                                    zipfs.arrayBufferToBase64(file.content) + '">';
                            }
                            str += '</td></tr>';
                        });
                        str += '</table>';
                        document.getElementById('panel').innerHTML = str;
                    });
                };
                reader.readAsArrayBuffer(this.files[0]);
            }
            function checkExt(name, ext) {
                return name.lastIndexOf(ext) === name.length - ext.length;
            }
            function log(msg) {
                document.getElementById('console').innerHTML += `<br />${msg}`; 
            }
            function clearlog() {
                document.getElementById('console').innerHTML = ''; 
            }
        }
    </script>
</body>

</html>

然後core.xml會變成這樣的json:

{
  "cp:coreProperties": {
    "xmlns:cp": "http://schemas.openxmlformats.org/package/2006/metadata/core-properties",
    "xmlns:dc": "http://purl.org/dc/elements/1.1/",
    "xmlns:dcterms": "http://purl.org/dc/terms/",
    "xmlns:dcmitype": "http://purl.org/dc/dcmitype/",
    "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
    "dc:title": {
      "_value": "Colour Pencils PowerPoint Template"
    },
    "dc:creator": {
      "_value": "Presentation Magazine"
    },
    "cp:lastModifiedBy": {
      "_value": "Hsu Ping Feng"
    },
    "cp:revision": {
      "_value": "58"
    },
    "dcterms:created": {
      "xsi:type": "dcterms:W3CDTF",
      "_value": "2009-11-03T13:35:13Z"
    },
    "dcterms:modified": {
      "xsi:type": "dcterms:W3CDTF",
      "_value": "2016-10-14T08:03:12Z"
    }
  }
}

這樣就比較好讀一點了。如果有重複的tag name,底下的property會改成陣列,例如docProps/app.xml底下的vt:variant

{
  "Properties": {
    "xmlns": "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties",
    "xmlns:vt": "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes",
    "TotalTime": {
      "_value": "1986"
    },
    "Words": {
      "_value": "471"
    },
    "Application": {
      "_value": "Microsoft Macintosh PowerPoint"
    },
    "PresentationFormat": {
      "_value": "如螢幕大小 (4:3)"
    },
    "Paragraphs": {
      "_value": "106"
    },
    "Slides": {
      "_value": "8"
    },
    "Notes": {
      "_value": "7"
    },
    "HiddenSlides": {
      "_value": "0"
    },
    "MMClips": {
      "_value": "0"
    },
    "ScaleCrop": {
      "_value": "false"
    },
    "HeadingPairs": {
      "vt:vector": {
        "size": "6",
        "baseType": "variant",
        "vt:variant": [
          {
            "vt:lpstr": {
              "_value": "使用字型"
            }
          },
          {
            "vt:i4": {
              "_value": "3"
            }
          },
          {
            "vt:lpstr": {
              "_value": "佈景主題"
            }
          },
          {
            "vt:i4": {
              "_value": "2"
            }
          },
          {
            "vt:lpstr": {
              "_value": "投影片標題"
            }
          },
          {
            "vt:i4": {
              "_value": "8"
            }
          }
        ]
      }
    },
  ...
  }
...
}

今天比較累,就先這樣,不然沒時間打ESO了....


上一篇
第九天:今天是奮發的星期四
下一篇
第十一天:又到了週六
系列文
中年失業大叔的耍廢日記30

1 則留言

我要留言

立即登入留言