Best JavaScript code snippet using playwright-internal
llsif_cardviewer.js
Source:llsif_cardviewer.js  
...422}423424/* toMemberName425====================================================================== */426function toMemberName(card, shortname) {427  if(!members_data) return '';428429  var mem_data = members_data.members.find(function(elem) { return elem.u == card.u; });430  if(!mem_data) return '';431  return shortname ? mem_data.s : mem_data.n;432}433434/* toSkillType435====================================================================== */436function toSkillType(card) {437  if(!card) return 'ç¡ã';438  if(Object.values(SKILL).indexOf(card.y) == -1) return 'ç¡ã';439  return SKILL_NAME[String(card.y)];440}441442/* toSkillDesc443====================================================================== */444function toSkillDesc(card, skill_level) {445  if(!card) return '';446  if(card.y == 0) return 'ç¡ã';447  if(skill_level == 'max') skill_level = card.k.length;448  if(skill_level > card.k.length || skill_level < 1) return '';449450  var sk = card.k[skill_level - 1];451452  var sk_target = '';453  if(card.e != 0) {454    switch(card.e[0]) {455      case EFFECT_TARGET.SUBUNIT:456        if(Object.values(SUBUNIT).indexOf(card.e[1]) != -1) sk_target = SUBUNIT_NAME[String(card.e[1])]; break;457      case EFFECT_TARGET.GROUPGRADE:458        if(Object.values(GROUP).indexOf(card.e[1]) != -1) sk_target = GROUP_NAME[String(card.e[1])] + card.e[2] + 'å¹´ç';459        break;460    }461  }462463  var sk_trigger = '', sk_chance = sk.r + '%ã®ç¢ºçã§';464  switch(card.t) {465    case TRIGGER.TIMER:    sk_trigger = sk.t + 'ç§ãã¨ã«'; break;466    case TRIGGER.ICON:     sk_trigger = 'ãªãºã ã¢ã¤ã³ã³' + sk.t + 'åãã¨ã«'; break;467    case TRIGGER.COMBO:    sk_trigger = 'ã³ã³ã' + sk.t + 'ãéæãããã¨ã«'; break;468    case TRIGGER.SCORE:    sk_trigger = 'ã¹ã³ã¢' + sk.t + 'éæãã¨ã«'; break;469    case TRIGGER.PERFECT:  sk_trigger = 'PERFECTã' + sk.t + 'åéæãããã¨ã«'; break;470    case TRIGGER.STARICON: sk_trigger = 'ã¹ã¿ã¼ã¢ã¤ã³ã³PERFECT' + sk.t + 'åãã¨ã«'; break;471    case TRIGGER.CHAIN:    sk_trigger = 'èªèº«ãé¤ã' + sk_target + 'ã®ç¹æããã¹ã¦çºåããã¨'; break;472    default: return '';473  }474475  var skill_desc;476  switch(card.y) {477    case SKILL.TIMINGBOOST_S:478      skill_desc = sk_trigger + sk_chance + 'å¤å®ã' + sk.s + 'ç§éå°ãå¼·åããã'; break;479    case SKILL.TIMINGBOOST_L:480      skill_desc = sk_trigger + sk_chance + 'å¤å®ã' + sk.s + 'ç§éå¼·åããã'; break;481    case SKILL.RECOVERY:482      skill_desc = sk_trigger + sk_chance + 'ä½åã' + sk.v + 'å復ãã'; break;483    case SKILL.SCOREUP:484      skill_desc = sk_trigger + sk_chance + 'ã¹ã³ã¢ã' + sk.v + 'å¢ãã'; break;485    case SKILL.SKILLCHANCE:486      skill_desc = sk_trigger + sk_chance + sk.s + 'ç§éä»ã®ç¹æã®çºå確çã' + sk.v + 'åã«ãªã'; break;487    case SKILL.SKILLREPEAT:488      skill_desc = sk_trigger + sk_chance + 'ç´åã«çºåããç¹æãªãã¼ã以å¤ã®ç¹æå¹æãçºåãã'; break;489    case SKILL.PERFECTUP:490      skill_desc = sk_trigger + sk_chance + sk.s + 'ç§éPERFECTæã®ã¿ããSCOREã' + sk.v + 'å¢ãã'; break;491    case SKILL.COMBOFEVER:492      skill_desc = sk_trigger + sk_chance + sk.s + 'ç§éã³ã³ãæ°ã«å¿ãã¦ã¿ããSCOREãå¢ãã(' + sk.v + 'ï½' + (sk.v * 10) + 'ã®éã§å¤å)'; break;493    case SKILL.PARAMSYNC:494      skill_desc = sk_trigger + sk_chance + sk.s + 'ç§é' + sk_target + 'ã®ããããã¨åã屿§Pã«ãªã'; break;495    case SKILL.SKILLBOOST:496      skill_desc = sk_trigger + sk_chance + '次ã«çºåããç¹æã®Lvã' + sk.v + 'ã¢ãããã'; break;497    case SKILL.PARAMUP:498      skill_desc = sk_trigger + sk_chance + sk.s + 'ç§é' + sk_target + 'ã®å±æ§Pã' + sk.v + '%UPãã'; break;499    default: return 'ç¡ã';500  }501502  if(card.hasOwnProperty('li')) { if(card.li > 0) skill_desc += '(æå¤§' + card.li + 'åã¾ã§)'; }503  return skill_desc;504}505506/* toCenterSkillName507====================================================================== */508function toCenterSkillName(card) {509  return '';510}511512513/* toCenterSkillDesc514====================================================================== */515function toCenterSkillDesc(card) {516  var cs_desc, e_attr;517518  if(!members_data) return '';519  if(!card) return 'ç¡ã';520  if(card.l == 0) return 'ç¡ã';521  switch(card.l.t) {522    case LEADER_SKILL.SMILE:523      e_attr = ATTR_NAME[ATTR.SMILE]; cs_desc = 'ã¹ãã¤ã«Pã' + card.l.v + '%UPãã'; break;524    case LEADER_SKILL.PURE:525      e_attr = ATTR_NAME[ATTR.PURE]; cs_desc = 'ãã¥ã¢Pã' + card.l.v + '%UPãã'; break;526    case LEADER_SKILL.COOL:527      e_attr = ATTR_NAME[ATTR.COOL]; cs_desc = 'ã¯ã¼ã«Pã' + card.l.v + '%UPãã'; break;528    case LEADER_SKILL.PUREPRINCESS:529      e_attr = ATTR_NAME[ATTR.PURE]; cs_desc = 'ã¹ãã¤ã«Pã®' + card.l.v + '%åãã¥ã¢PãUPãã'; break;530    case LEADER_SKILL.COOLPRINCESS:531      e_attr = ATTR_NAME[ATTR.COOL]; cs_desc = 'ã¹ãã¤ã«Pã®' + card.l.v + '%åã¯ã¼ã«PãUPãã'; break;532    case LEADER_SKILL.SMILEANGEL:533      e_attr = ATTR_NAME[ATTR.SMILE]; cs_desc = 'ãã¥ã¢Pã®' + card.l.v + '%åã¹ãã¤ã«PãUPãã'; break;534    case LEADER_SKILL.COOLANGEL:535      e_attr = ATTR_NAME[ATTR.COOL]; cs_desc = 'ãã¥ã¢Pã®' + card.l.v + '%åã¯ã¼ã«PãUPãã'; break;536    case LEADER_SKILL.SMILEEMPRESS:537      e_attr = ATTR_NAME[ATTR.SMILE]; cs_desc = 'ã¯ã¼ã«Pã®' + card.l.v + '%åã¹ãã¤ã«PãUPãã'; break;538    case LEADER_SKILL.PUREEMPRESS:539      e_attr = ATTR_NAME[ATTR.PURE]; cs_desc = 'ã¯ã¼ã«Pã®' + card.l.v + '%åãã¥ã¢PãUPãã'; break;540  }541542  var cs_desc_ex = '';543  switch(card.l.e) {544    case EFFECT_TARGET.GROUP:545      cs_desc_ex = GROUP_NAME[card.l.a]; break;546    case EFFECT_TARGET.GRADE:547      cs_desc_ex = card.l.a + 'å¹´ç'; break;548    case EFFECT_TARGET.SUBUNIT:549      cs_desc_ex = SUBUNIT_NAME[card.l.a]; break;550    case EFFECT_TARGET.MEMBER:551      var mem_data1 = members_data.members.find(function(elem) { return elem.u == card.l.a; });552      var mem_data2 = members_data.members.find(function(elem) { return elem.u == card.l.b; });553      cs_desc_ex = mem_data1.s;554      if(card.l.b != 0) cs_desc_ex += 'ã' + mem_data2.s;555      break;556  }557  if(cs_desc_ex != '') cs_desc_ex = 'ï¼' + cs_desc_ex + 'ã®ã¡ã³ãã¼ã¯ããã«' + e_attr + 'Pã' + card.l.x + '%UPãã';558559  return cs_desc + cs_desc_ex;560}561562563564/* ----------------------------------------------------------------------565*  Card Detail566---------------------------------------------------------------------- */567568/* getCardParameter569====================================================================== */570function getCardParameter(card, level, bond) {571  var diff = param_diff.pattern.find(function(elem) { return elem.i == card.v; });572  diff = diff.p.find(function(elem) { return elem.l == level; });573574  var param = new Object;575  param.life = card.h + diff.h;576  param.smile = card.s + diff.s; param.pure = card.p + diff.p; param.cool = card.c + diff.c;577  switch(card.a) {578    case ATTR.SMILE: param.smile += bond; break;579    case ATTR.PURE:  param.pure += bond; break;580    case ATTR.COOL:  param.cool += bond; break;581  }582  return param;583}584585586/* showCardDetail587====================================================================== */588function showCardDetail(card, deckmem, getparam, update_func) {589  var detail_elem = document.createElement('div');590591  detail_elem.innerHTML = 592    '<div class="image_block">' +593      '<img id="data_cardimg" class="card_image" />' +594      '<div class="idolized_switch">' +595        '<div class="switch_button idolized">' +596          '<input type="radio" name="card_idolized" id="card_normal" value="normal" onchange="" />' +597          '<label for="card_normal">é常</label>' +598          '<input type="radio" name="card_idolized" id="card_idolized" value="idolized" onchange="" />' +599          '<label for="card_idolized">è¦é</label>' +600        '</div>' +601      '</div>' +602    '</div>' +603604    '<div class="detail_block">' +605      '<div class="detail_frame">' +606        '<div id="data_eponym" class="detail_title"></div>' +607        '<div id="data_member" class="card_detail text"></div>' +608      '</div>' +609610      '<div class="detail_frame">' +611        '<div class="card_detail nowrap">' +612          '<div class="detail_name">Lv</div>' +613          '<div class="detail_desc">' +614            '<div class="spin_box">' +615              '<button class="spindown_button"></button>' +616              '<input id="data_level" type="number" class="spin_value" min="1" readonly="readonly"/>' +617              '<button class="spinup_button"></button>' +618            '</div>' +619            '<div id="data_level_max" class="detail_text"></div>' +620            '<div class="min_max_button">' +621              '<button id="level_min" class="min_button"></button>' +622              '<button id="level_max" class="max_button"></button>' +623            '</div>' +624          '</div>' +625        '</div>' +626        '<div class="card_detail nowrap">' +627          '<div class="detail_name">çµ</div>' +628          '<div class="detail_desc">' +629            '<div class="spin_box">' +630              '<button class="spindown_button"></button>' +631              '<input id="data_bond" type="number" class="spin_value" min="0" readonly="readonly"/>' +632              '<button class="spinup_button"></button>' +633            '</div>' +634            '<div id="data_bond_max" class="detail_text"></div>' +635            '<div class="min_max_button">' +636              '<button id="bond_min" class="min_button"></button>' +637              '<button id="bond_max" class="max_button"></button>' +638            '</div>' +639          '</div>' +640        '</div>' +641        '<div class="card_detail nowrap">' +642          '<div class="param_life"><span id="data_life" class="param_num"></span></div>' +643          '<div class="param_smile"><span id="data_smile" class="param_num"></span></div>' +644          '<div class="param_pure"><span id="data_pure" class="param_num"></span></div>' +645          '<div class="param_cool"><span id="data_cool" class="param_num"></span></div>' +646        '</div>' +647      '</div>' +648649      '<div class="detail_frame">' +650        '<div class="card_detail nowrap">' +651          '<div class="detail_name">ç¹æ</div><div id="data_skilltype" class="detail_desc"></div>' +652        '</div>' +653        '<div class="card_detail nowrap">' +654          '<div class="detail_name">ç¹æå</div><div id="data_skillname" class="detail_desc"></div>' +655        '</div>' +656        '<div class="card_detail nowrap">' +657          '<div class="detail_name">ç¹æLv</div>' +658          '<div class="detail_desc">' +659            '<div class="spin_box">' +660              '<button class="spindown_button"></button>' +661              '<input id="data_skilllevel" type="number" class="spin_value" min="1" readonly="readonly"/>' +662              '<button class="spinup_button"></button>' +663            '</div>' +664            '<div id="data_skilllevel_max" class="detail_text"></div>' +665            '<div class="min_max_button">' +666              '<button id="skilllevel_min" class="min_button"></button>' +667              '<button id="skilllevel_max" class="max_button"></button>' +668            '</div>' +669          '</div>' +670        '</div>' +671        '<div class="card_detail nowrap">' +672          '<div class="detail_name">广</div><div id="data_skilldesc" class="detail_desc small"></div>' +673        '</div>' +674        '<div class="card_detail">' +675          '<div class="detail_name">ã»ã³ã¿ã¼ã¹ãã«</div><div id="data_centerskill" class="detail_desc small"></div>' +676        '</div>' +677        '<div class="card_detail nowrap">' +678          '<div class="detail_name">é¨å¡No.</div><div id="data_memberid" class="detail_desc small"></div>' +679        '</div>' +680      '</div>' +681    '</div>';682683684  if(deckmem == null) getparam = false;685  var diff = param_diff.pattern.find(function(elem) { return elem.i == card.v; });686  var level_max, level_maxup, bond_max; 687  if(getparam) {688    level_max = card.o || deckmem.i ? diff.a : diff.b;689    level_maxup = card.o || deckmem.i ? diff.p[diff.p.length - 1].l : diff.b;690    bond_max = card.o || deckmem.i ? diff.o : diff.l;691  } else {692    level_max = card.o ? diff.a : diff.b;693    level_maxup = card.o ? diff.p[diff.p.length - 1].l : diff.b;694    bond_max = card.o ? diff.o : diff.l;695  }696  const sklevel_max = card.k[card.k.length - 1].l;697  const level = getparam ? deckmem.lv : 1, bond = getparam ? deckmem.b : 0;698  var param = getCardParameter(card, level, bond);699700701  function change_cardidolized(radio) {702    if(!radio.checked) return;703    const new_idolized = radio.value == 'idolized';704    const get_level = parseFloat(document.getElementById('data_level').value);705    const get_bond = parseFloat(document.getElementById('data_bond').value);706    var new_levelmax = new_idolized ? diff.a : diff.b;707    const new_bondmax = new_idolized ? diff.o : diff.l;708709    document.getElementById('data_cardimg').src = toCardAssetPath(card, new_idolized);710    document.getElementById('data_level_max').textContent = '/' + new_levelmax;711    document.getElementById('data_bond_max').textContent = '/' + new_bondmax;712713    new_levelmax = new_idolized ? diff.p[diff.p.length - 1].l : diff.b;714    var input = document.getElementById('data_level');715    if(parseFloat(input.value) > new_levelmax) {716      input.value = new_levelmax; input.max = new_levelmax; change_maxvalue('data_level');717    }718    input.max = new_levelmax;719720    input = document.getElementById('data_bond');721    if(parseFloat(input.value) > new_bondmax) {722      input.value = new_bondmax; input.max = new_bondmax; ichange_maxvalue('data_bond');723    }724    input.max = new_bondmax;725  }726727  function change_card_param() {728    const new_level = parseFloat(document.getElementById('data_level').value);729    const new_bond = parseFloat(document.getElementById('data_bond').value);730    const new_param = getCardParameter(card, new_level, new_bond);731    document.getElementById('data_life').textContent = new_param.life;732    document.getElementById('data_smile').textContent = new_param.smile;733    document.getElementById('data_pure').textContent = new_param.pure;734    document.getElementById('data_cool').textContent = new_param.cool;735  }736737  function change_minvalue(elemid) {738    var input = document.getElementById(elemid); input.value = input.min; input.onchange();739    input.parentNode.querySelector('.spindown_button').disabled = true;740    input.parentNode.querySelector('.spinup_button').disabled = false;741  }742743  function change_maxvalue(elemid) {744    var input = document.getElementById(elemid); input.value = input.max; input.onchange();745    input.parentNode.querySelector('.spindown_button').disabled = false;746    input.parentNode.querySelector('.spinup_button').disabled = true;747  }748749  function change_maxlevel() {750    var input = document.getElementById('data_level');751    if(document.getElementById('card_idolized').checked) {752      input.value = parseFloat(input.value) >= diff.a ? input.max : diff.a;753    } else {754      input.value = input.max;755    }756    input.onchange();757    input.parentNode.querySelector('.spindown_button').disabled = false;758    input.parentNode.querySelector('.spinup_button').disabled = input.value == input.max;759  }760761  function change_maxskill() {762    var input = document.getElementById('data_skilllevel');763    input.value = parseFloat(input.value) >= MAX_SKILL ? input.max : MAX_SKILL;764    input.onchange();765    input.parentNode.querySelector('.spindown_button').disabled = false;766    input.parentNode.querySelector('.spinup_button').disabled = input.value == input.max;767  }768769  function update_deckmember() {770    if(deckmem == null) { closeDialog('card_detail_dlg'); return; }771772    const new_level = parseFloat(document.getElementById('data_level').value);773    const new_bond = parseFloat(document.getElementById('data_bond').value);774    const new_sklevel = parseFloat(document.getElementById('data_skilllevel').value);775    const new_idolized = getRadioValue('card_idolized') == 'idolized';776777    if(new_sklevel > MAX_SKILL) return;778779    deckmem.lv = new_level; deckmem.i = new_idolized; deckmem.b = new_bond; deckmem.sk = new_sklevel; 780    if(deckmem.id != card.i) { deckmem.id = card.i; deckmem.a_id = 0; deckmem.a_lv = 0; deckmem.sis = []; }781    closeDialog('card_detail_dlg'); update_func();782  }783784  detail_elem.querySelector('#card_normal').onchange = function() { change_cardidolized(this); }785  detail_elem.querySelector('#card_idolized').onchange = function() { change_cardidolized(this); }786787  detail_elem.querySelector('#data_level').onchange = function() { change_card_param(); }788  detail_elem.querySelector('#level_min').onclick = function() { change_minvalue('data_level'); }789  detail_elem.querySelector('#level_max').onclick = function() { change_maxlevel(); }790791  detail_elem.querySelector('#data_bond').onchange = function() { change_card_param(); }792  detail_elem.querySelector('#bond_min').onclick = function() { change_minvalue('data_bond'); }793  detail_elem.querySelector('#bond_max').onclick = function() { change_maxvalue('data_bond'); }794795  detail_elem.querySelector('#data_skilllevel').onchange = function() {796    document.getElementById('data_skilldesc').textContent = toSkillDesc(card, this.value);797    if(deckmem == null) return;798    var updatebtn = document.getElementById('card_detail_dlg').querySelector('footer > button.exec_button');799    updatebtn.disabled = parseFloat(document.getElementById('data_skilllevel').value) > MAX_SKILL800  }801  detail_elem.querySelector('#skilllevel_min').onclick = function() { change_minvalue('data_skilllevel'); }802  detail_elem.querySelector('#skilllevel_max').onclick = function() { change_maxskill(); }803804805  detail_elem.querySelector('#data_cardimg').src = toCardAssetPath(card, getparam ? deckmem.i : false);806  if(card.o) detail_elem.querySelector('#card_normal').disabled = true;807  if(card.o || (getparam ? deckmem.i : false)) {808    detail_elem.querySelector('#card_idolized').checked = true;809  } else {810    detail_elem.querySelector('#card_normal').checked = true;811  }812813  switch(card.a) {814    case ATTR.SMILE: detail_elem.className = 'detail_bg smile'; break;815    case ATTR.PURE:  detail_elem.className = 'detail_bg pure'; break;816    case ATTR.COOL:  detail_elem.className = 'detail_bg cool'; break;817  }818  detail_elem.querySelector('#data_eponym').textContent = card.n;819  detail_elem.querySelector('#data_member').textContent = toMemberName(card, false);820821  detail_elem.querySelector('#data_level').value = level;822  detail_elem.querySelector('#data_level').max = level_maxup;823  detail_elem.querySelector('#data_level_max').textContent = '/' + level_max;824  detail_elem.querySelector('#data_bond').value = bond;825  detail_elem.querySelector('#data_bond').max = bond_max;826  detail_elem.querySelector('#data_bond_max').textContent = '/' + bond_max;827828  detail_elem.querySelector('#data_life').textContent = param.life;829  detail_elem.querySelector('#data_smile').textContent = param.smile;830  detail_elem.querySelector('#data_pure').textContent = param.pure;831  detail_elem.querySelector('#data_cool').textContent = param.cool;832833  detail_elem.querySelector('#data_skilltype').textContent = toSkillType(card);834  detail_elem.querySelector('#data_skillname').textContent = card.m;835  detail_elem.querySelector('#data_skilllevel').value = getparam ? deckmem.sk : 1;836  detail_elem.querySelector('#data_skilllevel').max = sklevel_max;837  detail_elem.querySelector('#data_skilllevel_max').textContent = '/' + MAX_SKILL;838  detail_elem.querySelector('#data_skilldesc').textContent = toSkillDesc(card, getparam ? deckmem.sk : 1);839  detail_elem.querySelector('#data_centerskill').textContent = toCenterSkillDesc(card);840  detail_elem.querySelector('#data_memberid').textContent = card.i;841842  var spinboxs = detail_elem.getElementsByClassName('spin_box');843  for(var i = 0; i < spinboxs.length; i++) {844    var spin_input = spinboxs[i].querySelector('.spin_value');845    var spin_up = spinboxs[i].querySelector('.spinup_button');846    var spin_down = spinboxs[i].querySelector('.spindown_button');847    initSpinBox(spin_input, spin_up, spin_down);848  }849850  const btntext = deckmem != null ? '夿´ãã' : 'éãã';851  showDialog(detail_elem, '', 'card_detail_dlg', btntext, 1, update_deckmember, true, true);852}853854855856/* ----------------------------------------------------------------------857*  Card Search858---------------------------------------------------------------------- */859860/* viewCardList861====================================================================== */862function viewCardList(listelem, cards, pagenum, skill_level, select_func) {863  listelem.innerHTML = '';864  items_elem = document.createDocumentFragment();865866  const pageitem_min = (VIEW_PAGEITEM * (pagenum - 1)) + 1;867  const pageitem_max = Math.min(VIEW_PAGEITEM * pagenum, cards.length);868869  for(var i = pageitem_min; i <= pageitem_max; i++) {870    var elem = cards[i - 1];871872    var item_elem = document.createElement('div'); item_elem.className = 'card_item';873    item_elem.innerHTML = 874      '<div class="member_icon" data-unitnumber="0">' +875        '<img src="" class="member_img"><img src="" class="member_frame">' +876      '</div>' +877      '<div class="card_data">' +878        '<div class="card_name"></div>' +879        '<div class="card_detail nowrap">' +880          '<div class="detail_name">ç¹æ</div><div class="detail_desc skill_type"></div>' +881        '</div>' +882        '<div class="card_detail nowrap">' +883          '<div class="detail_name">广</div><div class="detail_desc skill_desc"></div>' +884        '</div>' +885        '<div class="card_param">' +886          '<div class="param_life"><span class="param_num"></span></div>' +887          '<div class="param_smile"><span class="param_num"></span></div>' +888          '<div class="param_pure"><span class="param_num"></span></div>' +889          '<div class="param_cool"><span class="param_num"></span></div>' +890        '</div>' +891      '</div>';892893    var cardrarity = '', cardeponym = '', membername = toMemberName(elem, false);894    switch(elem.r) {895      case RARITY.UR: cardrarity = 'UR'; break;896    }897    if(elem.n != '') cardeponym = 'ã' + elem.n + 'ã';898899    item_elem.querySelector('.member_icon').dataset.unitnumber = elem.i;900    item_elem.querySelector('.member_img').src = toIconAssetPath(elem, false);901    item_elem.querySelector('.member_frame').src = toIconFrameAssetPath(elem);902    item_elem.querySelector('.card_name').textContent = cardrarity + cardeponym + membername;903    item_elem.querySelector('.skill_type').textContent = toSkillType(elem);904    item_elem.querySelector('.skill_desc').textContent = toSkillDesc(elem, skill_level);905    item_elem.querySelector('.param_life > .param_num').textContent = elem.h;906    item_elem.querySelector('.param_smile > .param_num').textContent = elem.s;907    item_elem.querySelector('.param_pure > .param_num').textContent = elem.p;
...generateDotnetApi.js
Source:generateDotnetApi.js  
...51  const asyncSuffix = item.member && item.member.async ? 'Async' : '';52  if (item.clazz)53    return `<see cref="I${toTitleCase(item.clazz.name)}"/>`;54  else if (item.member)55    return `<see cref="I${toTitleCase(item.member.clazz.name)}.${toMemberName(item.member)}${asyncSuffix}"/>`;56  else if (item.option)57    return `<paramref name="${item.option}"/>`;58  else if (item.param)59    return `<paramref name="${item.param}"/>`;60  else61    throw new Error('Unknown link format.');62});63// get the template for a class64const template = fs.readFileSync(path.join(__dirname, 'templates', 'interface.cs'), 'utf-8');65// map the name to a C# friendly one (we prepend an I to denote an interface)66const classNameMap = new Map(documentation.classesArray.map(x => [x.name, `I${toTitleCase(x.name)}`]));67// map some types that we know of68classNameMap.set('Error', 'Exception');69classNameMap.set('TimeoutError', 'TimeoutException');70classNameMap.set('EvaluationArgument', 'object');71classNameMap.set('boolean', 'bool');72classNameMap.set('Serializable', 'T');73classNameMap.set('any', 'object');74classNameMap.set('Buffer', 'byte[]');75classNameMap.set('path', 'string');76classNameMap.set('URL', 'string');77classNameMap.set('RegExp', 'Regex');78classNameMap.set('Readable', 'Stream');79/**80 *81 * @param {string} kind82 * @param {string} name83 * @param {Documentation.MarkdownNode[]} spec84 * @param {string[]} body85 * @param {string} folder86 * @param {string} extendsName87 */88function writeFile(kind, name, spec, body, folder, extendsName = null, namespace = "Microsoft.Playwright") {89  const out = [];90  // console.log(`Generating ${name}`);91  if (spec)92    out.push(...XmlDoc.renderXmlDoc(spec, maxDocumentationColumnWidth));93  else {94    let ownDocumentation = documentedResults.get(name);95    if (ownDocumentation) {96      out.push('/// <summary>');97      out.push(`/// ${ownDocumentation}`);98      out.push('/// </summary>');99    }100  }101  if (extendsName === 'IEventEmitter')102    extendsName = null;103  if (body[0] === '')104    body = body.slice(1);105  out.push(`${kind} ${name}${extendsName ? ` : ${extendsName}` : ''}`);106  out.push('{');107  out.push(...body);108  out.push('}');109  let content = template.replace('[NAMESPACE]', namespace).replace('[CONTENT]', out.join(EOL));110  fs.writeFileSync(path.join(folder, name + '.cs'), content);111}112/**113 * @param {Documentation.Class} clazz 114 */115function renderClass(clazz) {116  const name = classNameMap.get(clazz.name);117  if (name === 'TimeoutException')118    return;119  const body = [];120  for (const member of clazz.membersArray) {121    if (member.alias.startsWith('RunAnd'))122      renderMember(member, clazz, { trimRunAndPrefix: true }, body);123    renderMember(member, clazz, {}, body);124  }125  writeFile(126      'public partial interface',127      name,128      clazz.spec,129      body,130      apiDir,131      clazz.extends ? `I${toTitleCase(clazz.extends)}` : null);132}133/**134 * @param {string} name135 * @param {Documentation.Type} type136 */137function renderModelType(name, type) {138  const body = [];139  // TODO: consider how this could be merged with the `translateType` check140  if (type.union141    && type.union[0].name === 'null'142    && type.union.length == 2) {143    type = type.union[1];144  }145  if (type.name === 'Array') {146    throw new Error('Array at this stage is unexpected.');147  } else if (type.properties) {148    for (const member of type.properties) {149      let fakeType = new Type(name, null);150      renderMember(member, fakeType, {}, body);151    }152  } else {153    console.log(type);154    throw new Error(`Not sure what to do in this case.`);155  }156  writeFile('public partial class', name, null, body, typesDir);157}158/**159 * @param {string} name160 * @param {string[]} literals161 */162function renderEnum(name, literals) {163  const body = [];164  for (let literal of literals) {165    // strip out the quotes166    literal = literal.replace(/[\"]/g, ``)167    let escapedName = literal.replace(/[-]/g, ' ')168      .split(' ')169      .map(word => customTypeNames.get(word) || word[0].toUpperCase() + word.substring(1)).join('');170    body.push(`[EnumMember(Value = "${literal}")]`);171    body.push(`${escapedName},`);172  }173  writeFile('public enum', name, null, body, enumsDir);174}175/**176 * @param {string} name177 * @param {Documentation.Type} type178 */179function renderOptionType(name, type) {180  const body = [];181  renderConstructors(name, type, body);182  for (const member of type.properties)183    renderMember(member, member.type, {}, body);184  writeFile('public class', name, null, body, optionsDir);185}186for (const element of documentation.classesArray) {187  renderClass(element);188}189for (let [name, type] of optionTypes)190  renderOptionType(name, type);191for (let [name, type] of modelTypes)192  renderModelType(name, type);193for (let [name, literals] of enumTypes)194  renderEnum(name, literals);195if (process.argv[3] !== "--skip-format") {196  // run the formatting tool for .net, to ensure the files are prepped197  execSync(`dotnet format -f "${outputDir}" --include-generated --fix-whitespace`);198}199/**200 * @param {string} name201 */202function toArgumentName(name) {203  return name === 'event' ? `@${name}` : name;204}205 /**206 * @param {Documentation.Member} member207 */208function toMemberName(member, makeAsync = false) {209  const assumedName = toTitleCase(member.alias || member.name);210  if (member.kind === 'interface')211    return `I${assumedName}`;212  if (makeAsync && member.async)213    return assumedName + 'Async';214  if (!makeAsync && assumedName.endsWith('Async'))215    return assumedName.substring(0, assumedName.length - 'Async'.length);216  return assumedName;217}218/**219 * @param {string} name220 * @returns {string}221 */222function toTitleCase(name) {223  return name.charAt(0).toUpperCase() + name.substring(1);224}225/**226 *227 * @param {string} name228 * @param {Documentation.Type} type229 * @param {string[]} out230 */231function renderConstructors(name, type, out) {232  out.push(`public ${name}(){}`);233  out.push('');234  out.push(`public ${name}(${name} clone) {`);235  out.push(`if(clone == null) return;`);236  type.properties.forEach(p => {237    let propType = translateType(p.type, type, t => generateNameDefault(p, name, t, type));238    let propName = toMemberName(p);239    const overloads = getPropertyOverloads(propType, p, propName, p.type);240    for (let { name } of overloads)241      out.push(`${name} = clone.${name};`);242  });243  out.push(`}`);244}245/**246 *247 * @param {Documentation.Member} member248 * @param {Documentation.Class|Documentation.Type} parent249 * @param {{nojson?: boolean, trimRunAndPrefix?: boolean}} options250 * @param {string[]} out251 */252function renderMember(member, parent, options, out) {253  let name = toMemberName(member);254  if (member.kind === 'method') {255    renderMethod(member, parent, name, { mode: 'options', trimRunAndPrefix: options.trimRunAndPrefix }, out);256    return;257  }258  /** @type string */259  let type = translateType(member.type, parent, t => generateNameDefault(member, name, t, parent));260  if (member.kind === 'event') {261    if (!member.type)262      throw new Error(`No Event Type for ${name} in ${parent.name}`);263    out.push('');264    if (member.spec)265      out.push(...XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth));266    out.push(`event EventHandler<${type}> ${name};`);267    return;268  }269  if (member.kind === 'property') {270    if (parent && member && member.name === 'children') {  // this is a special hack for Accessibility271      console.warn(`children property found in ${parent.name}, assuming array.`);272      type = `IEnumerable<${parent.name}>`;273    }274    const overloads = getPropertyOverloads(type, member, name, parent);275    for (let { type, name, jsonName } of overloads) {276      out.push('');277      if (member.spec)278        out.push(...XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth));279      if (!member.clazz)280        out.push(`${member.required ? '[Required]\n' : ''}[JsonPropertyName("${jsonName}")]`)281      if (!type.endsWith('?') && !member.required)282        type = `${type}?`;283      const requiredSuffix = type.endsWith('?') ? '' : ' = default!;';284      if (member.clazz)285        out.push(`public ${type} ${name} { get; }`);286      else287        out.push(`public ${type} ${name} { get; set; }${requiredSuffix}`);288    }289    return;290  }291  throw new Error(`Problem rendering a member: ${type} - ${name} (${member.kind})`);292}293/**294 *295 * @param {string} type296 * @param {Documentation.Member} member297 * @param {string} name298 * @param {Documentation.Class|Documentation.Type} parent299 * @returns [{ type: string; name: string; jsonName: string; }]300 */301function getPropertyOverloads(type, member, name, parent) {302  const overloads = [];303  if (type) {304    let jsonName = member.name;305    if (member.type.expression === '[string]|[float]')306      jsonName = `${member.name}String`;307    overloads.push({ type, name, jsonName });308  } else {309    for (const overload of member.type.union) {310      const t = translateType(overload, parent, t => generateNameDefault(member, name, t, parent));311      const suffix = toOverloadSuffix(t);312      overloads.push({ type: t, name: name + suffix, jsonName: member.name + suffix });313    }314  }315  return overloads;316}317/**318 *319 * @param {Documentation.Member} member320 * @param {string} name321 * @param {Documentation.Type} t322 * @param {*} parent323 */324function generateNameDefault(member, name, t, parent) {325  if (!t.properties326    && !t.templates327    && !t.union328    && t.expression === '[Object]')329    return 'object';330  // we'd get this call for enums, primarily331  let enumName = generateEnumNameIfApplicable(t);332  if (!enumName && member) {333    if (member.kind === 'method' || member.kind === 'property') {334      let names = [335        parent.alias || parent.name,336        toTitleCase(member.alias || member.name),337        toTitleCase(name),338      ];339      if (names[2] === names[1])340        names.pop(); // get rid of duplicates, cheaply341      let attemptedName = names.pop();342      let typesDiffer = function (left, right) {343        if (left.expression && right.expression)344          return left.expression !== right.expression;345        return JSON.stringify(right.properties) !== JSON.stringify(left.properties);346      }347      while (true) {348        // crude attempt at removing plurality349        if (attemptedName.endsWith('s')350          && !["properties", "httpcredentials"].includes(attemptedName.toLowerCase()))351          attemptedName = attemptedName.substring(0, attemptedName.length - 1);352        if (customTypeNames.get(attemptedName))353          attemptedName = customTypeNames.get(attemptedName);354        let probableType = modelTypes.get(attemptedName);355        if ((probableType && typesDiffer(t, probableType))356          || (["Value"].includes(attemptedName))) {357          if (!names.length)358            throw new Error(`Ran out of possible names: ${attemptedName}`);359          attemptedName = `${names.pop()}${attemptedName}`;360          continue;361        } else {362          registerModelType(attemptedName, t);363        }364        break;365      }366      return attemptedName;367    }368    if (member.kind === 'event') {369      return `${name}Payload`;370    }371  }372  return enumName || t.name;373}374/**375 * 376 * @param {Documentation.Type} type 377 * @returns 378 */379function generateEnumNameIfApplicable(type) {380  if (!type.union)381    return null;382  const potentialValues = type.union.filter(u => u.name.startsWith('"'));383  if ((potentialValues.length !== type.union.length)384    && !(type.union[0].name === 'null' && potentialValues.length === type.union.length - 1)) {385    return null; // this isn't an enum, so we don't care, we let the caller generate the name386  }387  return type.name;388}389/**390 * Rendering a method is so _special_, with so many weird edge cases, that it391 * makes sense to put it separate from the other logic.392 * @param {Documentation.Member} member393 * @param {Documentation.Class | Documentation.Type} parent394 * @param {string} name395 * @param {{396 *   mode: 'options'|'named'|'base',397 *   nodocs?: boolean,398 *   abstract?: boolean,399 *   public?: boolean,400 *   trimRunAndPrefix?: boolean,401 * }} options402 * @param {string[]} out403 */404function renderMethod(member, parent, name, options, out) {405  out.push('');406  if (options.trimRunAndPrefix)407    name = name.substring('RunAnd'.length);408  /**409   * @param {Documentation.Type} type 410   * @returns 411   */412  function resolveType(type) {413    return translateType(type, parent, (t) => {414      let newName = `${parent.name}${toMemberName(member)}Result`;415      documentedResults.set(newName, `Result of calling <see cref="I${toTitleCase(parent.name)}.${toMemberName(member, true)}"/>.`);416      return newName;417    });418  }419  /** @type {Map<string, string[]>} */420  const paramDocs = new Map();421  const addParamsDoc = (paramName, docs) => {422    if (paramName.startsWith('@'))423      paramName = paramName.substring(1);424    if (paramDocs.get(paramName) && paramDocs.get(paramName) !== docs)425      throw new Error(`Parameter ${paramName} already exists in the docs.`);426    paramDocs.set(paramName, docs);427  };428  /** @type {string} */429  let type = null;430  // need to check the original one431  if (member.type.name === 'Object' || member.type.name === 'Array') {432    let innerType = member.type;433    let isArray = false;434    if (innerType.name === 'Array') {435      // we want to influence the name, but also change the object type436      innerType = member.type.templates[0];437      isArray = true;438    }439    if (innerType.expression === '[Object]<[string], [string]>') {440      // do nothing, because this is handled down the road441    } else if (!isArray && !innerType.properties) {442      type = `dynamic`;443    } else {444      type = classNameMap.get(innerType.name);445      if (!type)446        type = resolveType(innerType);447      if (isArray)448        type = `IReadOnlyList<${type}>`;449    }450  }451  type = type || resolveType(member.type);452  // TODO: this is something that will probably go into the docs453  // translate simple getters into read-only properties, and simple454  // set-only methods to settable properties455  if (member.args.size == 0456    && type !== 'void'457    && !name.startsWith('Get')458    && !name.startsWith('PostDataJSON')459    && !name.startsWith('As')) {460    if (!member.async) {461      if (member.spec && !options.nodocs)462        out.push(...XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth));463      out.push(`${type} ${name} { get; }`);464      return;465    }466  }467  // HACK: special case for generics handling!468  if (type === 'T') {469    name = `${name}<T>`;470  }471  // adjust the return type for async methods472  if (member.async) {473    if (type === 'void')474      type = `Task`;475    else476      type = `Task<${type}>`;477  }478  // render args479  /** @type {string[]} */480  let args = [];481  /** @type {string[]} */482  let explodedArgs = [];483  /** @type {Map<string, string>} */484  let argTypeMap = new Map([]);485  /**486   *487   * @param {string} innerArgType488   * @param {string} innerArgName489   * @param {Documentation.Member} argument490   * @param {boolean} isExploded491   */492  function pushArg(innerArgType, innerArgName, argument, isExploded = false) {493    if (innerArgType === 'null')494      return;495    const requiredPrefix = (argument.required || isExploded) ? "" : "?";496    const requiredSuffix = (argument.required || isExploded) ? "" : " = default";497    var push = `${innerArgType}${requiredPrefix} ${innerArgName}${requiredSuffix}`;498    if (isExploded)499      explodedArgs.push(push)500    else501      args.push(push);502    argTypeMap.set(push, innerArgName);503  }504  /**505   * @param {Documentation.Member} arg506   */507  function processArg(arg) {508    if (options.trimRunAndPrefix && arg.name === 'action')509      return;510    if (arg.name === 'options') {511      if (options.mode === 'options' || options.mode === 'base') {512        const optionsType = member.clazz.name + name.replace('<T>', '') + 'Options';513        optionTypes.set(optionsType, arg.type);514        args.push(`${optionsType}? options = default`);515        argTypeMap.set(`${optionsType}? options = default`, 'options');516        addParamsDoc('options', ['Call options']);517      } else {518        arg.type.properties.forEach(processArg);519      }520      return;521    }522    if (arg.type.expression === '[string]|[path]') {523      let argName = toArgumentName(arg.name);524      pushArg("string?", `${argName} = default`, arg);525      pushArg("string?", `${argName}Path = default`, arg);526      if (arg.spec) {527        addParamsDoc(argName, XmlDoc.renderTextOnly(arg.spec, maxDocumentationColumnWidth));528        addParamsDoc(`${argName}Path`, [`Instead of specifying <paramref name="${argName}"/>, gives the file name to load from.`]);529      }530      return;531    } else if (arg.type.expression === '[boolean]|[Array]<[string]>') {532      // HACK: this hurts my brain too533      // we split this into two args, one boolean, with the logical name534      let argName = toArgumentName(arg.name);535      let leftArgType = translateType(arg.type.union[0], parent, (t) => { throw new Error('Not supported'); });536      let rightArgType = translateType(arg.type.union[1], parent, (t) => { throw new Error('Not supported'); });537      pushArg(leftArgType, argName, arg);538      pushArg(rightArgType, `${argName}Values`, arg);539      addParamsDoc(argName, XmlDoc.renderTextOnly(arg.spec, maxDocumentationColumnWidth));540      addParamsDoc(`${argName}Values`, [`The values to take into account when <paramref name="${argName}"/> is <code>true</code>.`]);541      return;542    }543    const argName = toArgumentName(arg.alias || arg.name);544    const argType = translateType(arg.type, parent, (t) => generateNameDefault(member, argName, t, parent));545    if (argType === null && arg.type.union) {546      // we might have to split this into multiple arguments547      let translatedArguments = arg.type.union.map(t => translateType(t, parent, (x) => generateNameDefault(member, argName, x, parent)));548      if (translatedArguments.includes(null))549        throw new Error('Unexpected null in translated argument types. Aborting.');550      let argDocumentation = XmlDoc.renderTextOnly(arg.spec, maxDocumentationColumnWidth);551      for (const newArg of translatedArguments) {552        pushArg(newArg, argName, arg, true); // push the exploded arg553        addParamsDoc(argName, argDocumentation);554      }555      args.push(arg.required ? 'EXPLODED_ARG' : 'OPTIONAL_EXPLODED_ARG');556      return;557    }558    addParamsDoc(argName, XmlDoc.renderTextOnly(arg.spec, maxDocumentationColumnWidth));559    if (argName === 'timeout' && argType === 'decimal') {560      args.push(`int timeout = 0`); // a special argument, we ignore our convention561      return;562    }563    pushArg(argType, argName, arg);564  }565  let modifiers = '';566  if (options.abstract)567    modifiers = 'protected abstract ';568  if (options.public)569    modifiers = 'public ';570  member.argsArray571    .sort((a, b) => b.alias === 'options' ? -1 : 0) //move options to the back to the arguments list572    .forEach(processArg);573  574  let body = ';';575  if (options.mode === 'base') {576    // Generate options -> named transition.577    const tokens = [];578    for (const arg of member.argsArray) {579      if (arg.name === 'action' && options.trimRunAndPrefix)580        continue;581      if (arg.name !== 'options') {582        tokens.push(toArgumentName(arg.name));583        continue;584      }585      for (const opt of arg.type.properties) {586        // TODO: use translate type here?587        if (opt.type.union && !opt.type.union[0].name.startsWith('"') && opt.type.union[0].name !== 'null' && opt.type.expression !== '[string]|[Buffer]') {588          // Explode overloads.589          for (const t of opt.type.union) {590            const suffix = toOverloadSuffix(translateType(t, parent));591            tokens.push(`${opt.name}${suffix}: options.${toMemberName(opt)}${suffix}`);592          }593        } else {594          tokens.push(`${opt.alias || opt.name}: options.${toMemberName(opt)}`);595        }596      }597    }598    body = `599{600    options ??= new ${member.clazz.name}${name}Options();601    return ${toAsync(name, member.async)}(${tokens.join(', ')});602}`;603  }604  if (!explodedArgs.length) {605    if (!options.nodocs) {606      out.push(...XmlDoc.renderXmlDoc(member.spec, maxDocumentationColumnWidth));607      paramDocs.forEach((value, i) => printArgDoc(i, value, out));608    }...AirBasix.js
Source:AirBasix.js  
1/**2 * AirBasix 3 * Author: Paul McDowell4 * 5 * @description AirBasix (Airbase + Wix ) enables synchronizing airtable bases to6 * wix collections. This is the stand-alone version contained below. The newer 7 * "current" version that is found via npm is contained in the source directory. 8 * This version has been left intact for those that want an easier to read and9 * more guided version of the program that doesn't require them to implement a10 * wrapper on the node module for executing against potentially multiple bases11 * and collections. This is a 'one and done' design.12 * 13 */14/*15 * If you're not sure how this all works, the following three keys are the 16 * most important things you need to change. Please note, for security purposes17 * make a secondary airtable account and grant it read-only access to your airtable18 * base, then use the API key for that user here. That way if it becomes compromised19 * 1) your data source remains uncorrupted and 2) you can easily change the key or20 * restrict the account from having access.21 */22const airtableApiKey = ''; // the per-user key from your read-only airtable account23const airtableBaseId = ''; // the ID of the base - you can find this in your api docs24/*25 * The name of the collection we intend to store our synchronized data in.26 * NOTE: This collection is going to be code-managed, and thus SHOULD NOT27 * BE USED FOR OTHER ENTRIES. Data not in the airtable source WILL be deleted28 * from the wix collection at every synchronization.29 */30const wixAirtableStore = 'Places'; 31/*32 * The name of the view we want to use (typically your default table name). If you don't want to use33 * the default view, change this to the view name of your choice.34 */35const airtableRootDb = 'Places'; 36const Airtable = require('airtable'); 37const baseApi = new Airtable({apiKey: airtableApiKey}).base(airtableBaseId);38const wixDataOpts = { 'suppressAuth' : true };39import wixData from 'wix-data';40// This is universal to all wix collections, and will likely break everything if you41// change it. 42// ex: const wixIdName = '_id';43const wixIdName = '_id';44/*45 * The following are field detection assumptions made based on my own needs. You may46 * need to change some of these based on your own assumptions of how things should 47 * be organized in airtables.48 */49// atid is an arbitrary airtable Id field for tracking purposes.50const wixAirtableIdName = 'atid';51const airtableTagsSubstring = 'tags';52const shadowTagFieldSuffix = 'shadow';53const generateShadowTagFields = true; // if you don't want shadow fields for using tags in dataset processing, set to false54const airtableAddressSubstring = 'address';55/*56 * If you need to use maps on your wix site based on airtable address data, you'll need to add a secondary field in airtable57 * that contains the geocode info for each address. This can be created by using the Maps App in Airtable. 58 */59const airtableGeocodeFieldName = 'geocode';60/**61 * Begins the process of synchronizing an airtables db and views with a wix collection.62 * This is the main entry point for a backend-only synchronizing module.63 * PLEASE NOTE: Due to the sensitive nature of the processes involved, you should not64 * run this on a front-end. This is a backend only module.65 */66export async function ManualUpdate() {67	await SyncViews();68	console.log("completed update");69}70/**71 * Processes views provided in the views constant, relative to the configured base api.72 * If the same Id is present in multiple airtable views the duplicates are skipped.73 */74async function SyncViews() {75	var presentIds = [];76	let noErrorsFound = true;77	/* For the chosen view, iterate over all the pages contained in that view and collect78     * that record data for use below.	79     */80	let atrecords = await baseApi(airtableRootDb)81		.select({pageSize: 100})82		.all();83		84	atrecords.forEach(function(atrecord) { 85		var currId = atrecord.id;86		if(presentIds.indexOf(currId) >= 0) {87			return; // skip IDs we've already processed if dupes are found. 88		}89		90		presentIds.push(currId);91		wixData.query(wixAirtableStore)		    92			.eq(wixAirtableIdName, currId) 93			.find()94			.then(function(wixrecords) {95				if(wixrecords.items.length > 0) {96					UpdateRecord(atrecord, wixrecords.items[0]);97				} else {98					InsertRecord(atrecord);99				}100			}).catch((error) => {101                noErrorsFound = false;102				LogError(error.message, error.code);103		});104		105	});106	console.log(`Updated ${presentIds.length} records.`);107	// clean up missing records if no errors were found in processing.108    if(noErrorsFound)109	    await RemoveMissingRecords(presentIds);110}111/**112 * Process error handling centrally for this module.113 * @param {string} errorMsg - The message describing the error received.114 * @param {string} code - The error code received, usually from the API. 115 */116function LogError (errorMsg, code) {117	console.log(`Error code ${code}: ${errorMsg}`);118}119/**120 * Inserts a new Airtable entry into the wix collection.121 * @param {object} atRecord - Airtable Record object.122 */123function InsertRecord(atRecord) {124	var wixItem = wixItem || {125		[wixAirtableIdName] : atRecord.id,126		'createdTime': atRecord.createdTime127	};128	129	wixItem = CopyAirtableFieldsToWixRecord(atRecord.fields, wixItem);130	UpdateWix(wixItem);131}132/**133 * Update the record data for a given entry existing in the wix collection.134 * @param {object} atRecord - Airtable Record object.135 * @param {object} wixRecord - Wix record object.136 */137function UpdateRecord(atRecord, wixRecord) {138	var wixItem = wixRecord || {139		[wixIdName] : wixItem._id,140		[wixAirtableIdName] : atRecord.id,141		'createdTime': atRecord.createdTime142	};143	wixItem = CopyAirtableFieldsToWixRecord(atRecord.fields, wixItem);144	UpdateWix(wixItem);145}146/**147 * Copies the fields from airtable to the appropriate wix record entries148 * based on a pre-determined field map.149 * @param {object} atFields - The Fields entry from the Airtable Record.150 * @param {object} wixRecord - The record being sent to wix, preloaded with151 * required ID and timestamp properties.152 * @returns {object} A WixRecord object with the appropriate data entries added.153 */154function CopyAirtableFieldsToWixRecord(atFields, wixRecord) {155	for(var member in atFields) { // automated field processing156		if(typeof(atFields) === 'function')157			continue; // skip over functions, only process data members. 158		159		var data = atFields[member];160		// this camelCases the member name so it fits with the fields used in Wix.161		var toMemberName = member.toLowerCase().replace('/','').replace(/(?:^\w|[A-Z]|\b\w)/g, (word,index) => index == 0 ? word.toLowerCase() : word.toUpperCase()).replace(/\s+/g,'');162		if(Array.isArray(atFields[member])) {163			var dt = typeof(data[0]);164			if(dt === "string") {165				// strings should map cleanly across without processing.166				wixRecord[toMemberName] = data;167				168                if(generateShadowTagFields) {169                    // if this is a tags field add a shadow field with concatinated values170                    // so we can use it for filtering, since wix doesn't support filtering 171                    // by tags for some dumb reason.172                    if(member.toLowerCase().indexOf(airtableTagsSubstring) >= 0) {173                        wixRecord[toMemberName + shadowTagFieldSuffix] = data.join(',');174                    }175                }176			}177			else if(dt === 'object') {178				if(data[0].hasOwnProperty('type') && data[0].type.indexOf('image') >= 0) {179					// process as an array of images.180					var images = [];181					data.forEach((image) => images.push({type: 'image', src: image.url}));182					wixRecord[toMemberName] = images;183				}184			}185		}186		else { 187			/* If this is an address place it into an object with the value as "formatted"188             * otherwise check to see if it's a geocode entry for marking map locations.189             */190			if(member.toLowerCase().indexOf(airtableAddressSubstring) >= 0) {191				wixRecord[toMemberName] = { formatted: atFields[member]};192			}193			else if(member.toLowerCase().indexOf(airtableGeocodeFieldName) >= 0) {194				// geocode data in airtable is stored in a base64 string, so we need to 195                // break that out into json and then parse it into an object we can work with.196				var jsonString = new Buffer(atFields[member].split(' ')[1], 'base64').toString();197				var jsonObj = JSON.parse(jsonString);198				var wixObj = {'formatted': jsonObj.o.formattedAddress,199					'location': {200						'latitude': jsonObj.o.lat,201						'longitude': jsonObj.o.lng202					},203					//'subdivision': "OK", // You may need to add these for your purpose, if so look at the geocode entries. 204					//'country': "US"205				};206				wixRecord[toMemberName] = wixObj;207			} else {208				// process as basic strings and numbers, which need no translation.209				wixRecord[toMemberName] = atFields[member];210			}211		}212	}213	return wixRecord;214}215/**216 * Updates the wix collection with the specified entry, either calling insert217 * or update as needed via the wix-data.save function.218 * @param {object} wixItem - The fully formed WixRecord for entry.219 */220function UpdateWix(wixItem) {221	wixData.save(wixAirtableStore, wixItem, wixDataOpts).then((results) => {222		// the item was updated successfully223		console.debug("item " + results._id + " created.");224	}).catch((error) => { LogError(error.message, error.code); });225}226/**227 * Gathers a list of Ids contained in the wix collection that do not match Ids synchronized from228 * Airtable. These Ids likely need to be deleted, thus making that a simpler process.229 * @param {Array} keepids The ids we want to keep in the table, stored as an array of strings230 * @returns An array of wix collection Ids not matching the supplied list (limited to 1,000 Ids)231 */232async function getOrphanIds(keepids) {233	let foundIds = [];234	let records = await wixData.query(wixAirtableStore)235			.limit(1000) // this arbitrary limit is created by Wix. Should their policy change, so can this236			.not(wixData.query(wixAirtableStore).hasSome([wixAirtableIdName], keepids))237			.find(wixDataOpts);238	records.items.forEach(record => foundIds.push(record._id));239	return foundIds; 240}241/**242 * Processes all the Ids on Wix against a supplied list of airtable ids. 243 * Any that don't match what is in airtable are deleted. NOTE: Wix has an artificial limit based244 * on implementation that will only remove up to 1,000 IDs at a time. If you need to remove more,245 * I suggest you expand on this section to enable that process. 246 * @param {string[]} keepids - The list of all valid Ids from airtable.247 */248async function RemoveMissingRecords(keepids) {249	if(keepids == null || keepids == undefined || keepids.length == 0)250		return;251	252	console.log(keepids);253	let removeids = await getOrphanIds(keepids);254	255	if(removeids.length == 0) { // skip out if we're empty.256		console.log(`no orphans found, ending removal.`);257		return;258	}259	console.log(`${removeids.length} orphans found.`);260	261	wixData.bulkRemove(wixAirtableStore, removeids, wixDataOpts)262	.then((results) => {263		if(results.skipped > 0)264		{ console.error('skipped ' + results.skipped + ' items.'); }265		console.log('Removed ' + removeids.length +' orphaned entries.')266	}).catch((error) => {LogError(error.errorMsg, error.code)});...sendController.js
Source:sendController.js  
1const { Request, Member } = require("../models");2const { getAnswer, getAnswerFromButtonGroup } = require("../utils/lib");3const maxStrikes = 4;4const sendController = async (bot, msg) => {5  const chatId = msg.chat.id;6  const selectedUserId = +msg.text.split(" ")[1];7  if (selectedUserId == msg.from.id) {8    bot.sendMessage(chatId, "Seriously dude, Why you sending to yourself?ð¤¦");9    return;10  }11  const requestsSentByThisUser = await Request.find({ fromId: msg.from.id })12    .lean()13    .exec();14  if (requestsSentByThisUser.length === maxStrikes) {15    bot.sendMessage(16      chatId,17      `You've already used all your ${maxStrikes} chances.\n`18    );19    await Member.findOneAndUpdate({ chatId }, { allStrikesOut: true });20    return;21  }22  const requestsReceivedToThisUser = await Request.find({ toId: msg.from.id })23    .lean()24    .exec();25  const selectedUserMatch = requestsReceivedToThisUser.find(26    (m) => m.fromId === selectedUserId27  );28  const currUserName =29    msg.from.first_name ||30    "" + msg.from.last_name + "" ||31    "@" + msg.from.username;32  if (selectedUserMatch) {33    const { fromUserName, fromId: matchedUserId } = selectedUserMatch;34    const name = fromUserName;35    bot.sendMessage(36      chatId,37      `Congragulations, You've got a match!\nBoth you and ${name} can spend Valentine's day togetherâ¤ï¸\nNotification sent to ${name} informing the match!ð`38    );39    bot.sendMessage(40      matchedUserId,41      `Congragulations, ${42        msg.from.username ? "@" + msg.from.username : currUserName43      } has found a match with you!\nNow go call them up and spend Valentine's day together!ð¯`44    );45    selectedUserMatch.matched = true;46    Request.findByIdAndUpdate(selectedUserMatch._id, { matched: true })47      .then(() => console.log("request status updated"))48      .catch((err) => console.log("Error in updating request status: " + err));49    return;50  }51  const toMember = await Member.findOne({ userId: selectedUserId }).exec();52  if (requestsReceivedToThisUser.length) {53    toMemberName = toMember.fullName;54    await bot.sendMessage(55      chatId,56      `${toMemberName} was not the one who sent you the message.\nBut you can send an anonymous message to ${toMemberName} to see if ${toMemberName} have some feelings towards you!`57    );58    requestsReceivedToThisUser59      .filter((r) => !r.matched)60      .forEach((r) => {61        bot.sendMessage(62          r.fromId,63          `Hi, ${r.toUserName} tried selecting someone, but unfortunately that wasn't you.`64        );65      });66    // await Member.findByIdAndUpdate();67  }68  const { extraMsg } = await getAnswer(69    {70      key: "extraMsg",71      prompt: `Enter the special message you want to send to ${toMember.fullName}. eg: "I'm your classmate and we used to go together by College Bus. I don't talk very much, but I really like you!"`,72      // formatter: (val) => (val === "." ? null : val),73    },74    chatId,75    bot76  );77  console.log(extraMsg);78  const confirmButtons = ["Yes, Nothing to loseð¤", "No, I'm good with myself"];79  const crushMsg = `Hi, this is to let you know that someone from MEC have feelings towards you. Here is the anonymous message sent by that special person to you:\n---\n${extraMsg}\n---\n\nHave some idea who this is from? Enter /start to check or try /faq or /help to know more details about this bot.`;80  const confirmSendMessage = await getAnswerFromButtonGroup(81    {82      key: "confirmSendMessage",83      prompt: `The following message will be sent to ${toMember.fullName}:\n${crushMsg}\n\n\n-------\nDo you want to confirm this?`,84      buttons: confirmButtons,85      condition: (val) => confirmButtons.includes(val),86      formatter: (val) => val === confirmButtons[0],87    },88    chatId,89    bot90  );91  if (confirmSendMessage) {92    try {93      bot94        .sendMessage(selectedUserId, crushMsg)95        .then((r) => console.log("Message sent successfully"));96      bot.sendMessage(chatId, `Message has been sent to ${toMember.fullName}`);97      const newRequest = new Request({98        fromId: msg.chat.id,99        toId: selectedUserId,100        matched: false,101        fromUserName: currUserName,102        toUserName: toMember.fullName,103      });104      await newRequest.save();105      // console.log(savedRequest);106    } catch (err) {107      bot.sendMessage(chatId, "There's been some error. Please try again");108      console.log("Error: " + err);109    }110  } else {111    bot.sendMessage(112      chatId,113      "Cancelled sending message.\nEnter /start to try again."114    );115  }116};...frepleybbs.js
Source:frepleybbs.js  
1$(function () {2    $("#jqGrid").jqGrid({3        url: baseURL + 'sys/frepleybbs/list',4        datatype: "json",5        colModel: [			6			{ label: 'itemid', name: 'itemid', index: 'itemid', width: 50, key: true,hidden:true },7			{ label: '主贴', name: 'title', index: 'title', width: 80 },8			{ label: 'åå¤å
容', name: 'repleyContent', index: 'repley_content', width: 80 ,hidden: true},9			{ label: 'åå¤äºº', name: 'repleyname', index: 'repleyname', width: 80 },10			{ label: 'ipå°å', name: 'ip', index: 'ip', width: 80 }, 			11			{ label: '被è·å¸äºº', name: 'tomembername', index: 'tomembername', width: 80 },12			//{ label: 'æå±å°åº', name: 'areaid', index: 'areaid', width: 80 },13			{ label: '楼å±', name: 'floor', index: 'floor', width: 80 }, 			14			{ label: 'æ·»å æ¶é´', name: 'addtime', index: 'addtime', width: 80 },15			{ label: 'æä½', name: 'contentDetail', index: 'content_detail', width: 80,formatter: function (cellvalue, options, rowdata) {16					var str = '<a  href="javascript:void(0);" onclick="clickth('+ rowdata.itemid +')">æ¥ç</a>';17					return str;18				} }19        ],20		viewrecords: true,21        height: 385,22        rowNum: 10,23		rowList : [10,30,50],24        rownumbers: true, 25        rownumWidth: 25, 26        autowidth:true,27        multiselect: true,28        pager: "#jqGridPager",29        jsonReader : {30            root: "page.list",31            page: "page.currPage",32            total: "page.totalPage",33            records: "page.totalCount"34        },35        prmNames : {36            page:"page", 37            rows:"limit", 38            order: "order"39        },40        gridComplete:function(){41        	//éègridåºé¨æ»å¨æ¡42        	$("#jqGrid").closest(".ui-jqgrid-bdiv").css({ "overflow-x" : "hidden" }); 43        }44    });45});46var vm = new Vue({47	el:'#rrapp',48	data:{49		showList: true,50		title: null,51		fRepleyBbs: {}52	},53	methods: {54		query: function () {55			vm.reload();56		},57		add: function(){58			vm.showList = false;59			vm.title = "æ°å¢";60			vm.fRepleyBbs = {};61		},62		update: function (event) {63			var itemid = getSelectedRow();64			if(itemid == null){65				return ;66			}67			vm.showList = false;68            vm.title = "ä¿®æ¹";69            70            vm.getInfo(itemid)71		},72		saveOrUpdate: function (event) {73			var url = vm.fRepleyBbs.itemid == null ? "sys/frepleybbs/save" : "sys/frepleybbs/update";74			$.ajax({75				type: "POST",76			    url: baseURL + url,77                contentType: "application/json",78			    data: JSON.stringify(vm.fRepleyBbs),79			    success: function(r){80			    	if(r.code === 0){81						alert('æä½æå', function(index){82							vm.reload();83						});84					}else{85						alert(r.msg);86					}87				}88			});89		},90		del: function (event) {91			var itemids = getSelectedRows();92			if(itemids == null){93				return ;94			}95			96			confirm('ç¡®å®è¦å é¤éä¸çè®°å½ï¼', function(){97				$.ajax({98					type: "POST",99				    url: baseURL + "sys/frepleybbs/delete",100                    contentType: "application/json",101				    data: JSON.stringify(itemids),102				    success: function(r){103						if(r.code == 0){104							alert('æä½æå', function(index){105								$("#jqGrid").trigger("reloadGrid");106							});107						}else{108							alert(r.msg);109						}110					}111				});112			});113		},114		getInfo: function(itemid){115			$.get(baseURL + "sys/frepleybbs/info/"+itemid, function(r){116                vm.fRepleyBbs = r.fRepleyBbs;117            });118		},119		reload: function (event) {120			vm.showList = true;121			var page = $("#jqGrid").jqGrid('getGridParam','page');122			$("#jqGrid").jqGrid('setGridParam',{ 123                page:page124            }).trigger("reloadGrid");125		}126	}127});128//æ¥ç详ç»129function clickth(id) {130	$.get(baseURL + "sys/frepleybbs/info/" + id, function (r) {131		if(r.code==0){132			var strbug = "";133			strbug+="<table>åå¤å
容ï¼"+r.fRepleyBbs.repleyContent+"<br/></table>";134			document.getElementById("showDetailDIV").innerHTML=strbug;135			layer.open({136				type: 1,137				// btn: savebug,138				skin: 'layui-layer-molv',139				title: "详æ
",140				area: ['600px', '500px'],141				shadeClose: false,142				content: jQuery("#showDetail")143			});144		}145	});...index.js
Source:index.js  
1var app = getApp()2const config = require('../../../../../../utils/config.js')3Page({4  /**5   * 页é¢çåå§æ°æ®6   */7  data: {8    toMemberName: '',9    toMemberId: '',10    imei: '',11    toMemberPhone: '',12    followerPhone: '',13    relationShip: '',14  },15  /**16   * çå½å¨æå½æ°--çå¬é¡µé¢å è½½17   */18  onLoad: function(options) {19    this.setData({20      imei: options.imei,21      toMemberId: options.toMemberId,22      toMemberPhone: options.toMemberPhone,23      toMemberName: options.toMemberName24    })25  },26  // è·åç¨æ·è¾å
¥çææºå·27  toGetFollowerPhone: function(e) {28    this.setData({29      followerPhone: e.detail.value30    })31  },32  // è·åå
³ç³»33  toGetFollowerRelationShip: function(e) {34    var index = e.currentTarget.dataset.id35    var relationShipChoosen = this.data.relationShips[index]36    this.setData({37      relationShip: relationShipChoosen,38      showRelationShipsModalStatus: false39    })40  },41  // è·åç¨æ·è¾å
¥çå
³ç³»42  enterRelation: function(e) {43    let length = this.data.relation44    if (length > 5) {45      wx.showToast({46        title: 'æå¤åªè½è¾å
¥6个å符ï¼',47        icon: 'none',48        duration: app.globalData.duration49      })50    } else {51      this.setData({52        relationShip: e.detail.value,53        showRelationShipsModalStatus: false54      })55    }56  },57  // ç¹å»æ·»å æå58  doAddFollower: function(e) {59    var userId = app.globalData.userId60    var followerPhone = this.data.followerPhone61    var imei = this.data.imei62    var relationShip = this.data.relationShip63    var toMemberId = this.data.toMemberId64    var toMemberPhone = this.data.toMemberPhone65    var toMemberName = this.data.toMemberName66    if (followerPhone.length < 11) {67      wx.showToast({68        title: '请è¾å
¥æ£ç¡®ææºå·',69        icon: 'none',70        duration: app.globalData.duration71      })72    } else {73      if (relationShip === '') {74        wx.showToast({75          title: '请è¾å
¥æ¨ä¸ä½©æ´è
å
³ç³»',76          icon: 'none',77          duration: app.globalData.duration78        })79      } else {80        app.http.postRequest(config.postAddFollower, {81          userId: userId,82          followerPhone: followerPhone,83          imei: imei,84          relation: relationShip,85          toMemberId: toMemberId,86          toMemberPhone: toMemberPhone,87          toMemberName: toMemberName88        }).then(res => {89          if (res.data.code === 'GN00000') {90            wx.showToast({91              title: 'å
³æ³¨è®¾å¤æå!',92              duration:app.globalData.duration93            });94            setTimeout(function(){95              wx.navigateBack({96                delta: 197              })98            },500)99          } else if (res.data.code === 'GN60011') {100            wx.showToast({101              title: 'å·²å
³è该设å¤!',102              icon: 'none'103            })104          } else {105            wx.showToast({106              title: 'å
³æ³¨è®¾å¤å¤±è´¥ï¼è¯·ç¨åéè¯!',107              icon: 'none'108            })109          }110        })111      }112    }113  }...table.js
Source:table.js  
...50			tbody.insertRow().innerHTML = `51				<td>${fromPackageAndClassName(packageDep, memberDep)}</td>52				<td>${fromMemberName(memberDep)}</td>53				<td>→</td>54				<td>${toMemberName(memberDep)}</td>55				<td>${toPackageAndClassName(packageDep, memberDep)}</td>56			`;57		}58	}59	const table = document.createElement('table');60	table.appendChild(thead);61	table.appendChild(tbody);62	const tableWrapper = document.createElement('div');63	tableWrapper.id = 'table-wrapper';64	tableWrapper.appendChild(table);65	return tableWrapper;66}67function fromPackageAndClassName(packageDep, memberDep) {68	return [packageDep.from.relativeName, memberDep.from.className].filter(x => x).join('.');69}70function toPackageAndClassName(packageDep, memberDep) {71	return [packageDep.to.relativeName, memberDep.to.className].filter(x => x).join('.');72}73function fromMemberName(memberDep) {74	return memberDep.from.memberName !== null75		? memberDep.from.memberName.replace('<', '<').replace('>', '>')76		: '';77}78function toMemberName(memberDep) {79	return memberDep.to.memberName !== null80		? memberDep.to.memberName.replaceAll('<', '<').replaceAll('>', '>')81		: '<i>' + memberDep.type.toLowerCase().replaceAll('_', ' ') + '</i>';...dynamics.js
Source:dynamics.js  
12function dynamicsMessageType1(messages){3	eval("message = "+messages);4	document.write("<a target=_blank href=blog-home.action?tomember.id="+message.memberId+">");5	document.write(message.memberName);6	document.write("</a>_");7	document.write(message.date);8	document.write("å<a target=_blank href=blog-home.action?tomember.id="+message.tomemberId+">");9	document.write(message.tomemberName);10	document.write("</a>");11	document.write("å ä¸ºäºå¥½å");12}1314function dynamicsMessageType2(messages){15	eval("message = "+messages);16	document.write("<a target=_blank href='blog-home.action?tomember.id="+message.memberId+"'>");17	document.write(message.memberName);18	document.write("</a>_");19	document.write(message.date);20	document.write("åå¸äºæ°æ¥å¿");21	document.write("<a target=_blank href=blog-content.action?id="+message.articleId+"&&tomember.id="+message.memberId+">");22	document.write("\""+message.articleTitle+"\"");23	document.write("</a>");24}2526function dynamicsMessageType3(messages){27	eval("message = "+messages);28	document.write("<a target=_blank href=blog-home.action?tomember.id="+message.memberId+">");29	document.write(message.memberName);30	document.write("</a>_");31	document.write(message.date);32	document.write("åå¸äºæ°ä½å");33	document.write("<a target=_blank href=blog-content.action?id="+message.articleId+"&&tomember.id="+message.memberId+">");34	document.write("\""+message.articleTitle+"\"");35	document.write("</a>");36}3738function dynamicsMessageType4(messages){39	eval("message = "+messages);40	document.write("<a target=_blank href=blog-home.action?tomember.id="+message.memberId+">");41	document.write(message.memberName);42	document.write("</a>_");43	document.write(message.date);44	document.write("æ¶èäºæç« ");45	document.write("<a target=_blank href=../searcharticlecontent.action?article.id="+message.articleId+">");46	document.write("\""+message.articleTitle+"\"");47	document.write("</a>");48}4950//æ¥çç¨æ·å¨ææ´å¤51function getDynamicsMore(){52	var url = "member-dynamics-more.action";53	var data = {'ssuid':1};54	jQuery.post(url,data,function(data){55		56			$("#dynamicsMore").after(data);57			$("#dynamicsMore").hide();58	});
...Using AI Code Generation
1const { toMemberName } = require('playwright/lib/server/page');2const { toMemberName } = require('playwright/lib/server/elementHandler');3const { toMemberName } = require('playwright/lib/server/jsHandle');4const { toMemberName } = require('playwright/lib/server/frame');5const { toMemberName } = require('playwright/lib/server/worker');6const { toMemberName } = require('playwright/lib/server/browserContext');7const { toMemberName } = require('playwright/lib/server/browser');8const { toMemberName } = require('playwright/lib/server/browserType');9const { toMemberName } = require('playwright/lib/server/playwright');10const { toMemberName } = require('playwright/lib/server/connection');11const { toMemberName } = require('playwright/lib/server/dispatcher');12const { toMemberName } = require('playwright/lib/server/dispatcherConnection');13const { toMemberName } = require('playwright/lib/server/dispatcherScope');14const { toMemberName } = require('playwright/lib/server/dispatcherSession');15const { toMemberName } = require('playwright/lib/server/eventsDispatcher');16const { toMemberName } = require('playwright/lib/server/sdkObject');Using AI Code Generation
1const { toMemberName } = require('playwright/lib/utils/utils');2console.log(toMemberName('some string'));3const { toMemberName } = require('playwright/lib/utils/utils');4console.log(toMemberName('some string'));5const { toMemberName } = require('playwright/lib/utils/utils');6console.log(toMemberName('some string'));7const { toMemberName } = require('playwright/lib/utils/utils');8console.log(toMemberName('some string'));9const { toMemberName } = require('playwright/lib/utils/utils');10console.log(toMemberName('some string'));11const { toMemberName } = require('playwright/lib/utils/utils');12console.log(toMemberName('some string'));13const { toMemberName } = require('playwright/lib/utils/utils');14console.log(toMemberName('some string'));15const { toMemberName } = require('playwright/lib/utils/utils');16console.log(toMemberName('some string'));17const { toMemberName } = require('playwright/lib/utils/utils');18console.log(toMemberName('some string'));19const { toMemberName } = require('playwright/lib/utils/utils');20console.log(toMemberName('some string'));Using AI Code Generation
1const { toMemberName } = require('playwright/lib/utils/utils');2const name = toMemberName('some string');3console.log(name);4const { toMemberName } = require('playwright/lib/utils/utils');5const name = toMemberName('some string');6console.log(name);Using AI Code Generation
1const { toMemberName } = require('playwright/lib/utils/utils');2console.log(toMemberName('myMethod'));3console.log(toMemberName('myMethod1'));4console.log(toMemberName('myMethod2'));5const { toMemberName } = require('playwright/lib/utils/utils');6console.log(toMemberName('myMethod'));7console.log(toMemberName('myMethod1'));8console.log(toMemberName('myMethod2'));9const { toMemberName } = require('playwright/lib/utils/utils');10console.log(toMemberName('myMethod'));11console.log(toMemberName('myMethod1'));12console.log(toMemberName('myMethod2'));13const { toMemberName } = require('playwright/lib/utils/utils');14console.log(toMemberName('myMethod'));15console.log(toMemberName('myMethod1'));16console.log(toMemberName('myMethod2'));17const { toMemberName } = require('playwright/lib/utils/utils');18console.log(toMemberName('myMethod'));19console.log(toMemberName('myMethod1'));20console.log(toMemberName('myMethod2'));21const { toMemberName } = require('playwright/lib/utils/utils');22console.log(toMemberName('myMethod'));23console.log(toMemberName('myMethod1'));24console.log(toMemberName('myMethod2'));25const { toMemberName } = require('playwrightUsing AI Code Generation
1const { toMemberName } = require('playwright-core/lib/server/helper');2const name = toMemberName('someName');3console.log(name);4const { toMemberName } = require('playwright/lib/server/helper');5const name = toMemberName('someName');6console.log(name);7const { toMemberName } = require('playwright-chromium/lib/server/helper');8const name = toMemberName('someName');9console.log(name);10const { toMemberName } = require('playwright-firefox/lib/server/helper');11const name = toMemberName('someName');12console.log(name);13const { toMemberName } = require('playwright-webkit/lib/server/helper');14const name = toMemberName('someName');15console.log(name);16const { toMemberName } = require('playwright/lib/helper');17const name = toMemberName('someName');18console.log(name);19const { toMemberName } = require('playwright-chromium/lib/helper');20const name = toMemberName('someName');21console.log(name);22const { toMemberName } = require('playwright-firefox/lib/helper');23const name = toMemberName('someName');24console.log(name);25const { toMemberName } = require('playwright-webkit/lib/helper');26const name = toMemberName('someName');27console.log(name);28const { toMemberName } = require('playwright/lib/api/helper');29const name = toMemberName('someName');30console.log(name);31const { toMemberName } = require('playwright-chromium/lib/api/helper');32const name = toMemberName('someName');33console.log(name);34const { toMemberName } = require('playwright-firefoxUsing AI Code Generation
1import { toMemberName } from '@playwright/test/lib/server/frames';2export async function getMemberName(page) {3  const elementHandle = await page.$('div');4  const memberName = toMemberName(elementHandle);5  console.log(memberName);6}7const { toMemberName } = require('@playwright/test/lib/server/frames');8async function getMemberName(page) {9  const elementHandle = await page.$('div');10  const memberName = toMemberName(elementHandle);11  console.log(memberName);12}13import { toMemberName } from '@playwright/test/lib/server/frames';14const { toMemberName } = require('@playwright/test/lib/server/frames');15export async function getMemberName(page) {16  const elementHandle = await page.$('div');17  const memberName = toMemberName(elementHandle);18  console.log(memberName);19}20async function getMemberName(page) {21  const elementHandle = await page.$('div');22  const memberName = toMemberName(elementHandle);23  console.log(memberName);24}25import { toMemberName } from '@playwright/test/lib/server/frames';26export async function getMemberName(page) {27  const elementHandle = await page.$('div');28  const memberName = toMemberName(elementHandle);29  console.log(memberName);30}31const { toMemberName } = require('@playwright/test/lib/server/frames');32async function getMemberName(page) {33  const elementHandle = await page.$('div');34  const memberName = toMemberName(elementHandle);35  console.log(memberName);36}37import { toMemberName } from '@playwright/test/lib/server/frames';38const { toMemberName } = require('@playwright/test/lib/server/frames');39export async function getMemberName(page) {40  const elementHandle = await page.$('div');41  const memberName = toMemberName(elementHandle);42  console.log(memberName);43}44async function getMemberName(page) {45  const elementHandle = await page.$('div');46  const memberName = toMemberName(elementHandle);47  console.log(memberName);48}49import {LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!
